// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <pollux/expression/special_form.h>

namespace kumo::pollux::exec {
    class ConstantExpr : public SpecialForm {
    public:
        explicit ConstantExpr(VectorPtr value)
            : SpecialForm(
                  value->type(),
                  std::vector<ExprPtr>(),
                  "literal",
                  !value->is_null_at(0) /* supportsFlatNoNullsFastPath */,
                  false /* trackCpuUsage */),
              needToSetIsAscii_{value->type()->is_varchar()} {
            POLLUX_CHECK_EQ(value->encoding(), VectorEncoding::Simple::CONSTANT);
            // sharedConstantValue_ may be modified so we should take our own copy to
            // prevent sharing across threads.
            sharedConstantValue_ =
                    BaseVector::wrap_in_constant(1, 0, std::move(value), true);
        }

        void evalSpecialForm(
            const SelectivityVector &rows,
            EvalCtx &context,
            VectorPtr &result) override;

        void evalSpecialFormSimplified(
            const SelectivityVector &rows,
            EvalCtx &context,
            VectorPtr &result) override;

        const VectorPtr &value() const {
            return sharedConstantValue_;
        }

        VectorPtr &mutableValue() {
            return sharedConstantValue_;
        }

        void setDefaultNullRowsSkipped(bool defaultNullRowsSkipped) {
            stats_.defaultNullRowsSkipped = defaultNullRowsSkipped;
        }

        std::string toString(bool recursive = true) const override;

        std::string toSql(
            std::vector<VectorPtr> *complexConstants = nullptr) const override;

    private:
        VectorPtr sharedConstantValue_;
        bool needToSetIsAscii_;
    };
} // namespace kumo::pollux::exec
